package com.atguigu.guli.service.sms.service.impl;


import com.atguigu.guli.service.base.handler.GuliException;
import com.atguigu.utils.FormUtils;
import com.atguigu.utils.HttpUtils;
import com.atguigu.utils.RandomUtils;
import com.atguigu.guli.service.base.result.ResultCodeEnum;
import com.atguigu.guli.service.sms.service.SmsService;
import com.atguigu.guli.service.sms.util.SmsProperties;
import com.google.gson.Gson;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class SmsServiceImpl implements SmsService {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    SmsProperties smsProperties;

    @Override
    public void send(String mobile) {
        //1、手机号码格式校验
        boolean flag = FormUtils.isMobile(mobile);
        if (!flag) {
            throw new GuliException(ResultCodeEnum.LOGIN_PHONE_ERROR);
        }
        //2、手机号码1分钟内是否获取过验证码判断+ 1天内获取注册验证码次数超过三次的校验
        String codePerminKey = "sms:regist:min:" + mobile;//1分钟的key
        if(redisTemplate.hasKey(codePerminKey)){
            throw new GuliException(ResultCodeEnum.SMS_SEND_BUSINESS_LIMIT_CONTROL);
        }
        //1天内的次数验证
        String codePerdayKey = "sms:regist:day:" + mobile;
        //查询获取验证码的次数：如果有再验证次数
        Object countObj = redisTemplate.opsForValue().get(codePerdayKey);
        int count = 0;
        if(countObj!=null){
            //之前获取过验证码
            count = Integer.parseInt(countObj.toString());
            if(count>=3){
                throw new GuliException(ResultCodeEnum.SMS_SEND_ERROR_BUSINESS_LIMIT_CONTROL);
            }
        }

        try {
            //3、手机号是否占用的校验:需要操作用户表查询数据
            //4、生成验证码发送短信
            String code = RandomUtils.getFourBitRandom();
            Map<String, String> headers = new HashMap<String, String>();
            //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
            headers.put("Authorization", "APPCODE " + smsProperties.getAppcode());
            Map<String, String> querys = new HashMap<String, String>();
            querys.put("mobile", mobile);
            querys.put("param", "code:" + code);
            querys.put("tpl_id", smsProperties.getTpl_id1());//短信模板id
            Map<String, String> bodys = new HashMap<String, String>();

            HttpResponse response = HttpUtils.doPost(smsProperties.getHost(), smsProperties.getPath(),
                    smsProperties.getMethod(), headers, querys, bodys);
            String resultStr = EntityUtils.toString(response.getEntity());
            Gson gson = new Gson();
            Map map = gson.fromJson(resultStr, Map.class);
            if (map == null || !"00000".equals(map.get("return_code"))) {
                //短信发送失败
                throw new GuliException(ResultCodeEnum.SMS_SEND_ERROR);
            }
            //5、如果发送成功 缓存验证码到redis，更新验证码获取频率
            //缓存验证码10分钟
            String codeKey = "sms:regist:code:" + mobile;//
            redisTemplate.opsForValue().set(codeKey, code, 10, TimeUnit.MINUTES);
            //一分钟内不能重复发送验证码的key的保存

            redisTemplate.opsForValue().set(codePerminKey, 1, 1, TimeUnit.MINUTES);
            //一天内获取次数不能超过3次
            //使用上面查询到的验证码的次数+1
            if (count!=0) {
                //第N次获取验证码
                redisTemplate.opsForValue().increment(codePerdayKey);
            } else {
                //第一次获取验证码： incr(key) :key如果不存在，相当于使用0+1
                long millis = new DateTime().plusDays(1).getMillis();//获取天的年月日 不包含时分秒
                System.out.println(millis);
                System.out.println(System.currentTimeMillis());
                //每天0点缓存失效
                long l = millis - System.currentTimeMillis();
                System.out.println(l);
                redisTemplate.opsForValue().set(codePerdayKey, 1, (millis - System.currentTimeMillis()), TimeUnit.MILLISECONDS);
            }
        } catch (Exception e) {
            throw new GuliException(ResultCodeEnum.SMS_SEND_ERROR  , e);
        }

    }
}
